/*!
 * @file Adafruit_NeoPixel.cpp
 *
 * @mainpage Arduino Library for driving Adafruit NeoPixel addressable LEDs,
 * FLORA RGB Smart Pixels and compatible devicess -- WS2811, WS2812, WS2812B,
 * SK6812, etc.
 *
 * @section intro_sec Introduction
 *
 * This is the documentation for Adafruit's NeoPixel library for the
 * Arduino platform, allowing a broad range of microcontroller boards
 * (most AVR boards, many ARM devices, ESP8266 and ESP32, among others)
 * to control Adafruit NeoPixels, FLORA RGB Smart Pixels and compatible
 * devices -- WS2811, WS2812, WS2812B, SK6812, etc.
 *
 * Adafruit invests time and resources providing this open source code,
 * please support Adafruit and open-source hardware by purchasing products
 * from Adafruit!
 *
 * @section author Author
 *
 * Written by Phil "Paint Your Dragon" Burgess for Adafruit Industries,
 * with contributions by PJRC, Michael Miller and other members of the
 * open source community.
 *
 * @section license License
 *
 * This file is part of the Adafruit_NeoPixel library.
 *
 * Adafruit_NeoPixel is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Adafruit_NeoPixel is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with NeoPixel. If not, see
 * <http://www.gnu.org/licenses/>.
 *
 */

#include "NeoPixel.h"

#if defined(NRF52) || defined(NRF52_SERIES)
#include "nrf.h"

// Interrupt is only disabled if there is no PWM device available
// Note: Adafruit Bluefruit nrf52 does not use this option
// #define NRF52_DISABLE_INT
#endif // if defined(NRF52) || defined(NRF52_SERIES)

/*!
   @brief   NeoPixel constructor when length, pin and pixel type are known
           at compile-time.
   @param   n  Number of NeoPixels in strand.
   @param   p  Arduino pin number which will drive the NeoPixel data in.
   @param   t  Pixel type -- add together NEO_* constants defined in
              Adafruit_NeoPixel.h, for example NEO_GRB+NEO_KHZ800 for
              NeoPixels expecting an 800 KHz (vs 400 KHz) data stream
              with color bytes expressed in green, red, blue order per
              pixel.
   @return  Adafruit_NeoPixel object. Call the begin() function before use.
 */
NeoPixel::NeoPixel(uint16_t n, uint8_t p, neoPixelType t) :
    begun(false), brightness(0), pixels(NULL), endTime(0) {
    updateType(t);
    updateLength(n);
    setPin(p);
}

/*!
   @brief   "Empty" NeoPixel constructor when length, pin and/or pixel type
           are not known at compile-time, and must be initialized later with
           updateType(), updateLength() and setPin().
   @return  Adafruit_NeoPixel object. Call the begin() function before use.
   @note    This function is deprecated, here only for old projects that
           may still be calling it. New projects should instead use the
           'new' keyword with the first constructor syntax (length, pin,
           type).
 */
NeoPixel::NeoPixel() :
#ifdef NEO_KHZ400
    is800KHz(true),
#endif // ifdef NEO_KHZ400
    begun(false), numLEDs(0), numBytes(0), pin(-1), brightness(0), pixels(NULL),
    rOffset(1), gOffset(0), bOffset(2), wOffset(1), endTime(0) {}

/*!
   @brief   Deallocate Adafruit_NeoPixel object, set data pin back to INPUT.
 */
NeoPixel::~NeoPixel() {
    free(pixels);
    if (pin >= 0) pinMode(pin, INPUT);
}

/*!
   @brief   Configure NeoPixel pin for output.
 */
void NeoPixel::begin(void) {
    if (pin >= 0) {
        pinMode(pin, OUTPUT);
        digitalWrite(pin, LOW);
    }
    begun = true;
}

/*!
   @brief   Change the length of a previously-declared Adafruit_NeoPixel
           strip object. Old data is deallocated and new data is cleared.
           Pin number and pixel format are unchanged.
   @param   n  New length of strip, in pixels.
   @note    This function is deprecated, here only for old projects that
           may still be calling it. New projects should instead use the
           'new' keyword with the first constructor syntax (length, pin,
           type).
 */
void NeoPixel::updateLength(uint16_t n) {
    free(pixels); // Free existing data (if any)

    // Allocate new data -- note: ALL PIXELS ARE CLEARED
    numBytes = n * ((wOffset == rOffset) ? 3 : 4);
    if ((pixels = (uint8_t*)malloc(numBytes))) {
        memset(pixels, 0, numBytes);
        numLEDs = n;
    } else {
        numLEDs = numBytes = 0;
    }
}

/*!
   @brief   Change the pixel format of a previously-declared
           Adafruit_NeoPixel strip object. If format changes from one of
           the RGB variants to an RGBW variant (or RGBW to RGB), the old
           data will be deallocated and new data is cleared. Otherwise,
           the old data will remain in RAM and is not reordered to the
           new format, so it's advisable to follow up with clear().
   @param   t  Pixel type -- add together NEO_* constants defined in
              Adafruit_NeoPixel.h, for example NEO_GRB+NEO_KHZ800 for
              NeoPixels expecting an 800 KHz (vs 400 KHz) data stream
              with color bytes expressed in green, red, blue order per
              pixel.
   @note    This function is deprecated, here only for old projects that
           may still be calling it. New projects should instead use the
           'new' keyword with the first constructor syntax
           (length, pin, type).
 */
void NeoPixel::updateType(neoPixelType t) {
    boolean oldThreeBytesPerPixel = (wOffset == rOffset); // false if RGBW

    wOffset = (t >> 6) & 0b11;                            // See notes in header file
    rOffset = (t >> 4) & 0b11;                            // regarding R/G/B/W offsets
    gOffset = (t >> 2) & 0b11;
    bOffset =  t       & 0b11;
#ifdef NEO_KHZ400
    is800KHz = (t < 256); // 400 KHz flag is 1<<8
#endif // ifdef NEO_KHZ400

    // If bytes-per-pixel has changed (and pixel data was previously
    // allocated), re-allocate to new size. Will clear any data.
    if (pixels) {
        boolean newThreeBytesPerPixel = (wOffset == rOffset);
        if (newThreeBytesPerPixel != oldThreeBytesPerPixel) updateLength(numLEDs);
    }
}

#if defined(ESP8266)
// ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
extern "C" void ICACHE_RAM_ATTR espShow(
    uint8_t pin, uint8_t* pixels, uint32_t numBytes, uint8_t type);
#elif defined(ESP32)
extern "C" void espShow(
    uint8_t pin, uint8_t* pixels, uint32_t numBytes, uint8_t type);
#endif // ESP8266

/*!
   @brief   Transmit pixel data in RAM to NeoPixels.
   @note    On most architectures, interrupts are temporarily disabled in
           order to achieve the correct NeoPixel signal timing. This means
           that the Arduino millis() and micros() functions, which require
           interrupts, will lose small intervals of time whenever this
           function is called (about 30 microseconds per RGB pixel, 40 for
           RGBW pixels). There's no easy fix for this, but a few
           specialized alternative or companion libraries exist that use
           very device-specific peripherals to work around it.
 */
void NeoPixel::show(void) {
    if (!pixels) return;

    // Data latch = 300+ microsecond pause in the output stream. Rather than
    // put a delay at the end of the function, the ending time is noted and
    // the function will simply hold off (if needed) on issuing the
    // subsequent round of data until the latch time has elapsed. This
    // allows the mainline code to start generating the next frame of data
    // rather than stalling for the latch.
    while (!canShow());
    // endTime is a private member (rather than global var) so that multiple
    // instances on different pins can be quickly issued in succession (each
    // instance doesn't delay the next).

    // In order to make this code runtime-configurable to work with any pin,
    // SBI/CBI instructions are eschewed in favor of full PORT writes via the
    // OUT or ST instructions. It relies on two facts: that peripheral
    // functions (such as PWM) take precedence on output pins, so our PORT-
    // wide writes won't interfere, and that interrupts are globally disabled
    // while data is being issued to the LEDs, so no other code will be
    // accessing the PORT. The code takes an initial 'snapshot' of the PORT
    // state, computes 'pin high' and 'pin low' values, and writes these back
    // to the PORT register as needed.

    // NRF52 may use PWM + DMA (if available), may not need to disable interrupt
#if !(defined(NRF52) || defined(NRF52_SERIES))
    noInterrupts(); // Need 100% focus on instruction timing
#endif // if !(defined(NRF52) || defined(NRF52_SERIES))

#ifdef __AVR__
    // AVR MCUs -- ATmega & ATtiny (no XMEGA) ---------------------------------

    volatile uint16_t
        i = numBytes; // Loop counter
    volatile uint8_t
    * ptr = pixels,   // Pointer to next byte
    b     = *ptr++,   // Current byte value
    hi,               // PORT w/output bit set high
    lo;               // PORT w/output bit set low

    // Hand-tuned assembly code issues data to the LED drivers at a specific
    // rate. There's separate code for different CPU speeds (8, 12, 16 MHz)
    // for both the WS2811 (400 KHz) and WS2812 (800 KHz) drivers. The
    // datastream timing for the LED drivers allows a little wiggle room each
    // way (listed in the datasheets), so the conditions for compiling each
    // case are set up for a range of frequencies rather than just the exact
    // 8, 12 or 16 MHz values, permitting use with some close-but-not-spot-on
    // devices (e.g. 16.5 MHz DigiSpark). The ranges were arrived at based
    // on the datasheet figures and have not been extensively tested outside
    // the canonical 8/12/16 MHz speeds; there's no guarantee these will work
    // close to the extremes (or possibly they could be pushed further).
    // Keep in mind only one CPU speed case actually gets compiled; the
    // resulting program isn't as massive as it might look from source here.

    // 8 MHz(ish) AVR ---------------------------------------------------------
#if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)

#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
    if (is800KHz) {
#endif // ifdef NEO_KHZ400

    volatile uint8_t n1, n2 = 0; // First, next bits out

    // Squeezing an 800 KHz stream out of an 8 MHz chip requires code
    // specific to each PORT register.

    // 10 instruction clocks per bit: HHxxxxxLLL
    // OUT instructions:              ^ ^    ^   (T=0,2,7)

    // PORTD OUTPUT ----------------------------------------------------

#if defined(PORTD)
 #if defined(PORTB) || defined(PORTC) || defined(PORTF)
    if (port == &PORTD) {
 #endif // defined(PORTB/C/F)

    hi = PORTD |  pinMask;
    lo = PORTD & ~pinMask;
    n1 = lo;
    if (b & 0x80) n1 = hi;

    // Dirty trick: RJMPs proceeding to the next instruction are used
    // to delay two clock cycles in one instruction word (rather than
    // using two NOPs). This was necessary in order to squeeze the
    // loop down to exactly 64 words -- the maximum possible for a
    // relative branch.

    asm volatile (
        "headD:"                   "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       // Clk  Pseudocode
        // Bit 7:
                                   "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             // 1    PORT = hi
                                                             "mov  %[n2]   , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   // 1    n2   = lo
                                                                                       "out  %[port] , %[n1]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         // 1    PORT = n1
                                                                                                                 "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               // 2    nop nop
                                                                                                                                           "sbrc %[byte] , 6"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     // 1-2  if(b & 0x40)
                                                                                                                                                                     "mov %[n2]   , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            // 0-1   n2 = hi
                                                                                                                                                                                              "out  %[port] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  // 1    PORT = lo
                                                                                                                                                                                                                        "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        // 2    nop nop
        // Bit 6:
                                                                                                                                                                                                                                                  "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // 1    PORT = hi
                                                                                                                                                                                                                                                                            "mov  %[n1]   , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    // 1    n1   = lo
                                                                                                                                                                                                                                                                                                      "out  %[port] , %[n2]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 1    PORT = n2
                                                                                                                                                                                                                                                                                                                                "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // 2    nop nop
                                                                                                                                                                                                                                                                                                                                                          "sbrc %[byte] , 5"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      // 1-2  if(b & 0x20)
                                                                                                                                                                                                                                                                                                                                                                                    "mov %[n1]   , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             // 0-1   n1 = hi
                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   // 1    PORT = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                       "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         // 2    nop nop
        // Bit 5:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               // 1    PORT = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "mov  %[n2]   , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     // 1    n2   = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "out  %[port] , %[n1]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           // 1    PORT = n1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 // 2    nop nop
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "sbrc %[byte] , 4"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       // 1-2  if(b & 0x10)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "mov %[n2]   , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // 0-1   n2 = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "out  %[port] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    // 1    PORT = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 2    nop nop
        // Bit 4:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // 1    PORT = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "mov  %[n1]   , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      // 1    n1   = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "out  %[port] , %[n2]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            // 1    PORT = n2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  // 2    nop nop
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "sbrc %[byte] , 3"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        // 1-2  if(b & 0x08)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "mov %[n1]   , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               // 0-1   n1 = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "out  %[port] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     // 1    PORT = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           // 2    nop nop
        // Bit 3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 // 1    PORT = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "mov  %[n2]   , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       // 1    n2   = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "out  %[port] , %[n1]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             // 1    PORT = n1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   // 2    nop nop
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "sbrc %[byte] , 2"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         // 1-2  if(b & 0x04)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "mov %[n2]   , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // 0-1   n2 = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "out  %[port] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      // 1    PORT = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            // 2    nop nop
        // Bit 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  // 1    PORT = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "mov  %[n1]   , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        // 1    n1   = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "out  %[port] , %[n2]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // 1    PORT = n2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    // 2    nop nop
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "sbrc %[byte] , 1"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 1-2  if(b & 0x02)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "mov %[n1]   , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 // 0-1   n1 = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "out  %[port] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                       // 1    PORT = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                             // 2    nop nop
        // Bit 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                   // 1    PORT = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "mov  %[n2]   , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                         // 1    n2   = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "out  %[port] , %[n1]"    "\n\t"                                                                                                                                                                                                                                                                                                                                               // 1    PORT = n1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                     // 2    nop nop
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "sbrc %[byte] , 0"        "\n\t"                                                                                                                                                                                                                                                                                           // 1-2  if(b & 0x01)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "mov %[n2]   , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                  // 0-1   n2 = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "out  %[port] , %[lo]"    "\n\t"                                                                                                                                                                                                                                        // 1    PORT = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "sbiw %[count], 1"        "\n\t"                                                                                                                                                                                                              // 2    i-- (don't act on Z flag yet)
        // Bit 0:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                    // 1    PORT = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "mov  %[n1]   , %[lo]"    "\n\t"                                                                                                                                                          // 1    n1   = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "out  %[port] , %[n2]"    "\n\t"                                                                                                                                // 1    PORT = n2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "ld   %[byte] , %a[ptr]+" "\n\t"                                                                                                      // 2    b = *ptr++
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "sbrc %[byte] , 7"        "\n\t"                                                                            // 1-2  if(b & 0x80)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "mov %[n1]   , %[hi]"    "\n\t"                                                   // 0-1   n1 = hi
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "out  %[port] , %[lo]"    "\n\t"                         // 1    PORT = lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "brne headD"              "\n" // 2    while(i) (Z flag set above)
        :[byte]  "+r" (b),
        [n1]    "+r" (n1),
        [n2]    "+r" (n2),
        [count] "+w" (i)
        :[port]   "I" (_SFR_IO_ADDR(PORTD)),
        [ptr]    "e" (ptr),
        [hi]     "r" (hi),
        [lo]     "r" (lo));

 #if defined(PORTB) || defined(PORTC) || defined(PORTF)
}

else // other PORT(s)
 #endif // defined(PORTB/C/F)
#endif // defined(PORTD)

    // PORTB OUTPUT ----------------------------------------------------

#if defined(PORTB)
 #if defined(PORTD) || defined(PORTC) || defined(PORTF)
    if (port == &PORTB) {
 #endif // defined(PORTD/C/F)

    // Same as above, just switched to PORTB and stripped of comments.
    hi = PORTB |  pinMask;
    lo = PORTB & ~pinMask;
    n1 = lo;
    if (b & 0x80) n1 = hi;

    asm volatile (
        "headB:"                   "\n\t"
                                   "out  %[port] , %[hi]"    "\n\t"
                                                             "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                       "out  %[port] , %[n1]"    "\n\t"
                                                                                                                 "rjmp .+0"                "\n\t"
                                                                                                                                           "sbrc %[byte] , 6"        "\n\t"
                                                                                                                                                                     "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                              "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                        "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                  "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                            "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                      "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                          "sbrc %[byte] , 5"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                    "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                       "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "sbrc %[byte] , 4"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "sbrc %[byte] , 3"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "sbrc %[byte] , 2"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "sbrc %[byte] , 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "sbrc %[byte] , 0"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "sbiw %[count], 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "ld   %[byte] , %a[ptr]+" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "sbrc %[byte] , 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "brne headB"              "\n"
        :[byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
        :[port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
        [lo] "r" (lo));

 #if defined(PORTD) || defined(PORTC) || defined(PORTF)
}
 #endif // if defined(PORTD) || defined(PORTC) || defined(PORTF)
 #if defined(PORTC) || defined(PORTF)
    else
 #endif // defined(PORTC/F)
#endif  // defined(PORTB)

    // PORTC OUTPUT ----------------------------------------------------

#if defined(PORTC)
 #if defined(PORTD) || defined(PORTB) || defined(PORTF)
    if (port == &PORTC) {
 #endif // defined(PORTD/B/F)

    // Same as above, just switched to PORTC and stripped of comments.
    hi = PORTC |  pinMask;
    lo = PORTC & ~pinMask;
    n1 = lo;
    if (b & 0x80) n1 = hi;

    asm volatile (
        "headC:"                   "\n\t"
                                   "out  %[port] , %[hi]"    "\n\t"
                                                             "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                       "out  %[port] , %[n1]"    "\n\t"
                                                                                                                 "rjmp .+0"                "\n\t"
                                                                                                                                           "sbrc %[byte] , 6"        "\n\t"
                                                                                                                                                                     "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                              "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                        "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                  "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                            "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                      "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                          "sbrc %[byte] , 5"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                    "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                       "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "sbrc %[byte] , 4"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "sbrc %[byte] , 3"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "sbrc %[byte] , 2"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "sbrc %[byte] , 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "sbrc %[byte] , 0"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "sbiw %[count], 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "ld   %[byte] , %a[ptr]+" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "sbrc %[byte] , 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "brne headC"              "\n"
        :[byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
        :[port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi),
        [lo] "r" (lo));

 #if defined(PORTD) || defined(PORTB) || defined(PORTF)
}
 #endif // defined(PORTD/B/F)
 #if defined(PORTF)
    else
 #endif // if defined(PORTF)
#endif // defined(PORTC)

    // PORTF OUTPUT ----------------------------------------------------

#if defined(PORTF)
 #if defined(PORTD) || defined(PORTB) || defined(PORTC)
    if (port == &PORTF) {
 #endif // defined(PORTD/B/C)

    hi = PORTF |  pinMask;
    lo = PORTF & ~pinMask;
    n1 = lo;
    if (b & 0x80) n1 = hi;

    asm volatile (
        "headF:"                   "\n\t"
                                   "out  %[port] , %[hi]"    "\n\t"
                                                             "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                       "out  %[port] , %[n1]"    "\n\t"
                                                                                                                 "rjmp .+0"                "\n\t"
                                                                                                                                           "sbrc %[byte] , 6"        "\n\t"
                                                                                                                                                                     "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                              "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                        "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                  "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                            "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                      "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                          "sbrc %[byte] , 5"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                    "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                       "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "sbrc %[byte] , 4"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "sbrc %[byte] , 3"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "sbrc %[byte] , 2"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "sbrc %[byte] , 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "mov  %[n2]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "out  %[port] , %[n1]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "sbrc %[byte] , 0"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "mov %[n2]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "sbiw %[count], 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "mov  %[n1]   , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "out  %[port] , %[n2]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "ld   %[byte] , %a[ptr]+" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "sbrc %[byte] , 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "mov %[n1]   , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "brne headF"              "\n"
        :[byte] "+r" (b), [n1] "+r" (n1), [n2] "+r" (n2), [count] "+w" (i)
        :[port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi),
        [lo] "r" (lo));

 #if defined(PORTD) || defined(PORTB) || defined(PORTC)
}
 #endif // defined(PORTD/B/C)
#endif  // defined(PORTF)

#ifdef NEO_KHZ400
} else {   // end 800 KHz, do 400 KHz
    // Timing is more relaxed; unrolling the inner loop for each bit is
    // not necessary. Still using the peculiar RJMPs as 2X NOPs, not out
    // of need but just to trim the code size down a little.
    // This 400-KHz-datastream-on-8-MHz-CPU code is not quite identical
    // to the 800-on-16 code later -- the hi/lo timing between WS2811 and
    // WS2812 is not simply a 2:1 scale!

    // 20 inst. clocks per bit: HHHHxxxxxxLLLLLLLLLL
    // ST instructions:         ^   ^     ^          (T=0,4,10)

    volatile uint8_t next, bit;

    hi   = *port |  pinMask;
    lo   = *port & ~pinMask;
    next = lo;
    bit  = 8;

    asm volatile (
        "head20:"                  "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       // Clk  Pseudocode    (T =  0)
                                   "st   %a[port], %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             // 2    PORT = hi     (T =  2)
                                                             "sbrc %[byte] , 7"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   // 1-2  if(b & 128)
                                                                                       "mov  %[next], %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 0-1   next = hi    (T =  4)
                                                                                                                "st   %a[port], %[next]"  "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                // 2    PORT = next   (T =  6)
                                                                                                                                          "mov  %[next] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                      // 1    next = lo     (T =  7)
                                                                                                                                                                    "dec  %[bit]"             "\n\t"                                                                                                                                                                                                                                                                                                                                                                            // 1    bit--         (T =  8)
                                                                                                                                                                                              "breq nextbyte20"         "\n\t"                                                                                                                                                                                                                                                                                                                                                  // 1-2  if(bit == 0)
                                                                                                                                                                                                                        "rol  %[byte]"            "\n\t"                                                                                                                                                                                                                                                                                                                        // 1    b <<= 1       (T = 10)
                                                                                                                                                                                                                                                  "st   %a[port], %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                              // 2    PORT = lo     (T = 12)
                                                                                                                                                                                                                                                                            "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                    // 2    nop nop       (T = 14)
                                                                                                                                                                                                                                                                                                      "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                          // 2    nop nop       (T = 16)
                                                                                                                                                                                                                                                                                                                                "rjmp .+0"                "\n\t"                                                                                                                                                                                                                // 2    nop nop       (T = 18)
                                                                                                                                                                                                                                                                                                                                                          "rjmp head20"             "\n\t"                                                                                                                                                                                      // 2    -> head20 (next bit out)
                                                                                                                                                                                                                                                                                                                                                                                    "nextbyte20:"              "\n\t"                                                                                                                                                           //                    (T = 10)
                                                                                                                                                                                                                                                                                                                                                                                                               "st   %a[port], %[lo]"    "\n\t"                                                                                                                                 // 2    PORT = lo     (T = 12)
                                                                                                                                                                                                                                                                                                                                                                                                                                         "nop"                     "\n\t"                                                                                                       // 1    nop           (T = 13)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "ldi  %[bit]  , 8"        "\n\t"                                                                             // 1    bit = 8       (T = 14)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "ld   %[byte] , %a[ptr]+" "\n\t"                                                   // 2    b = *ptr++    (T = 16)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "sbiw %[count], 1"        "\n\t"                         // 2    i--           (T = 18)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "brne head20"             "\n" // 2    if(i != 0) -> (next byte)
        :[port]  "+e" (port),
        [byte]  "+r" (b),
        [bit]   "+r" (bit),
        [next]  "+r" (next),
        [count] "+w" (i)
        :[hi]    "r" (hi),
        [lo]    "r" (lo),
        [ptr]   "e" (ptr));
}
#endif // NEO_KHZ400

    // 12 MHz(ish) AVR --------------------------------------------------------
#elif (F_CPU >= 11100000UL) && (F_CPU <= 14300000UL)

#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
    if (is800KHz) {
#endif // ifdef NEO_KHZ400

    // In the 12 MHz case, an optimized 800 KHz datastream (no dead time
    // between bytes) requires a PORT-specific loop similar to the 8 MHz
    // code (but a little more relaxed in this case).

    // 15 instruction clocks per bit: HHHHxxxxxxLLLLL
    // OUT instructions:              ^   ^     ^     (T=0,4,10)

    volatile uint8_t next;

    // PORTD OUTPUT ----------------------------------------------------

#if defined(PORTD)
 #if defined(PORTB) || defined(PORTC) || defined(PORTF)
    if (port == &PORTD) {
 #endif // defined(PORTB/C/F)

    hi   = PORTD |  pinMask;
    lo   = PORTD & ~pinMask;
    next = lo;
    if (b & 0x80) next = hi;

    // Don't "optimize" the OUT calls into the bitTime subroutine;
    // we're exploiting the RCALL and RET as 3- and 4-cycle NOPs!
    asm volatile (
        "headD:"                   "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    //        (T =  0)
                                   "out   %[port], %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          //        (T =  1)
                                                             "rcall bitTimeD"          "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // Bit 7  (T = 15)
                                                                                       "out   %[port], %[hi]"    "\n\t"
                                                                                                                 "rcall bitTimeD"          "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            // Bit 6
                                                                                                                                           "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                     "rcall bitTimeD"          "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        // Bit 5
                                                                                                                                                                                               "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                         "rcall bitTimeD"          "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    // Bit 4
                                                                                                                                                                                                                                                   "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                             "rcall bitTimeD"          "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // Bit 3
                                                                                                                                                                                                                                                                                                       "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                 "rcall bitTimeD"          "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            // Bit 2
                                                                                                                                                                                                                                                                                                                                                           "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                     "rcall bitTimeD"          "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        // Bit 1
        // Bit 0:
                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // 1    PORT = hi    (T =  1)
                                                                                                                                                                                                                                                                                                                                                                                                                                         "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    // 2    nop nop      (T =  3)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "ld   %[byte] , %a[ptr]+" "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 2    b = *ptr++   (T =  5)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[next]"  "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                // 1    PORT = next  (T =  6)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "mov  %[next] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                      // 1    next = lo    (T =  7)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "sbrc %[byte] , 7"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                            // 1-2  if(b & 0x80) (T =  8)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "mov %[next] , %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                   // 0-1    next = hi  (T =  9)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "nop"                     "\n\t"                                                                                                                                                                                                                                                                                                                                         // 1                 (T = 10)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "out  %[port] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                               // 1    PORT = lo    (T = 11)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "sbiw %[count], 1"        "\n\t"                                                                                                                                                                                                                                                                                     // 2    i--          (T = 13)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "brne headD"              "\n\t"                                                                                                                                                                                                                                                           // 2    if(i != 0) -> (next byte)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp doneD"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "bitTimeD:"               "\n\t"                                                                                                                                                                                                        //      nop nop nop     (T =  4)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port], %[next]"  "\n\t"                                                                                                                                                                               // 1    PORT = next     (T =  5)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "mov  %[next], %[lo]"    "\n\t"                                                                                                                                                      // 1    next = lo       (T =  6)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "rol  %[byte]"           "\n\t"                                                                                                                             // 1    b <<= 1         (T =  7)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "sbrc %[byte], 7"        "\n\t"                                                                                                    // 1-2  if(b & 0x80)    (T =  8)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "mov %[next], %[hi]"    "\n\t"                                                                            // 0-1   next = hi      (T =  9)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "nop"                    "\n\t"                                                   // 1                    (T = 10)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "out  %[port], %[lo]"    "\n\t"                          // 1    PORT = lo       (T = 11)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "ret"                    "\n\t" // 4    nop nop nop nop (T = 15)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "doneD:"                 "\n"
        :[byte]  "+r" (b),
        [next]  "+r" (next),
        [count] "+w" (i)
        :[port]   "I" (_SFR_IO_ADDR(PORTD)),
        [ptr]    "e" (ptr),
        [hi]     "r" (hi),
        [lo]     "r" (lo));

 #if defined(PORTB) || defined(PORTC) || defined(PORTF)
} else // other PORT(s)
 #endif // defined(PORTB/C/F)
#endif // defined(PORTD)

    // PORTB OUTPUT ----------------------------------------------------

#if defined(PORTB)
 #if defined(PORTD) || defined(PORTC) || defined(PORTF)
    if (port == &PORTB) {
 #endif // defined(PORTD/C/F)

    hi   = PORTB |  pinMask;
    lo   = PORTB & ~pinMask;
    next = lo;
    if (b & 0x80) next = hi;

    // Same as above, just set for PORTB & stripped of comments
    asm volatile (
        "headB:"                   "\n\t"
                                   "out   %[port], %[hi]"    "\n\t"
                                                             "rcall bitTimeB"          "\n\t"
                                                                                       "out   %[port], %[hi]"    "\n\t"
                                                                                                                 "rcall bitTimeB"          "\n\t"
                                                                                                                                           "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                     "rcall bitTimeB"          "\n\t"
                                                                                                                                                                                               "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                         "rcall bitTimeB"          "\n\t"
                                                                                                                                                                                                                                                   "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                             "rcall bitTimeB"          "\n\t"
                                                                                                                                                                                                                                                                                                       "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                 "rcall bitTimeB"          "\n\t"
                                                                                                                                                                                                                                                                                                                                                           "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                     "rcall bitTimeB"          "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                         "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "ld   %[byte] , %a[ptr]+" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[next]"  "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "mov  %[next] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "sbrc %[byte] , 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "mov %[next] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "nop"                     "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "sbiw %[count], 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "brne headB"              "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp doneB"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "bitTimeB:"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port], %[next]"  "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "mov  %[next], %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "rol  %[byte]"           "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "sbrc %[byte], 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "mov %[next], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "nop"                    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "out  %[port], %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "ret"                    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "doneB:"                 "\n"
        :[byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
        :[port] "I" (_SFR_IO_ADDR(PORTB)), [ptr] "e" (ptr), [hi] "r" (hi),
        [lo] "r" (lo));

 #if defined(PORTD) || defined(PORTC) || defined(PORTF)
}
 #endif // if defined(PORTD) || defined(PORTC) || defined(PORTF)
 #if defined(PORTC) || defined(PORTF)
    else
 #endif // defined(PORTC/F)
#endif  // defined(PORTB)

    // PORTC OUTPUT ----------------------------------------------------

#if defined(PORTC)
 #if defined(PORTD) || defined(PORTB) || defined(PORTF)
    if (port == &PORTC) {
 #endif // defined(PORTD/B/F)

    hi   = PORTC |  pinMask;
    lo   = PORTC & ~pinMask;
    next = lo;
    if (b & 0x80) next = hi;

    // Same as above, just set for PORTC & stripped of comments
    asm volatile (
        "headC:"                   "\n\t"
                                   "out   %[port], %[hi]"    "\n\t"
                                                             "rcall bitTimeC"          "\n\t"
                                                                                       "out   %[port], %[hi]"    "\n\t"
                                                                                                                 "rcall bitTimeC"          "\n\t"
                                                                                                                                           "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                     "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                               "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                         "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                                                                                   "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                             "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                                                                                                                                       "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                 "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                                                                                                                                                                                           "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                     "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                         "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "ld   %[byte] , %a[ptr]+" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[next]"  "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "mov  %[next] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "sbrc %[byte] , 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "mov %[next] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "nop"                     "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "sbiw %[count], 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "brne headC"              "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp doneC"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "bitTimeC:"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port], %[next]"  "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "mov  %[next], %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "rol  %[byte]"           "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "sbrc %[byte], 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "mov %[next], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "nop"                    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "out  %[port], %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "ret"                    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "doneC:"                 "\n"
        :[byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
        :[port] "I" (_SFR_IO_ADDR(PORTC)), [ptr] "e" (ptr), [hi] "r" (hi),
        [lo] "r" (lo));

 #if defined(PORTD) || defined(PORTB) || defined(PORTF)
}
 #endif // defined(PORTD/B/F)
 #if defined(PORTF)
    else
 #endif // if defined(PORTF)
#endif // defined(PORTC)

    // PORTF OUTPUT ----------------------------------------------------

#if defined(PORTF)
 #if defined(PORTD) || defined(PORTB) || defined(PORTC)
    if (port == &PORTF) {
 #endif // defined(PORTD/B/C)

    hi   = PORTF |  pinMask;
    lo   = PORTF & ~pinMask;
    next = lo;
    if (b & 0x80) next = hi;

    // Same as above, just set for PORTF & stripped of comments
    asm volatile (
        "headF:"                   "\n\t"
                                   "out   %[port], %[hi]"    "\n\t"
                                                             "rcall bitTimeC"          "\n\t"
                                                                                       "out   %[port], %[hi]"    "\n\t"
                                                                                                                 "rcall bitTimeC"          "\n\t"
                                                                                                                                           "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                     "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                               "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                         "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                                                                                   "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                             "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                                                                                                                                       "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                 "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                                                                                                                                                                                           "out   %[port], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                     "rcall bitTimeC"          "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                         "rjmp .+0"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "ld   %[byte] , %a[ptr]+" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "out  %[port] , %[next]"  "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "mov  %[next] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "sbrc %[byte] , 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "mov %[next] , %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "nop"                     "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "out  %[port] , %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "sbiw %[count], 1"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "brne headF"              "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp doneC"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "bitTimeC:"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "out  %[port], %[next]"  "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "mov  %[next], %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "rol  %[byte]"           "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "sbrc %[byte], 7"        "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "mov %[next], %[hi]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "nop"                    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "out  %[port], %[lo]"    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "ret"                    "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "doneC:"                 "\n"
        :[byte] "+r" (b), [next] "+r" (next), [count] "+w" (i)
        :[port] "I" (_SFR_IO_ADDR(PORTF)), [ptr] "e" (ptr), [hi] "r" (hi),
        [lo] "r" (lo));

 #if defined(PORTD) || defined(PORTB) || defined(PORTC)
}
 #endif // defined(PORTD/B/C)
#endif  // defined(PORTF)

#ifdef NEO_KHZ400
} else {   // 400 KHz
    // 30 instruction clocks per bit: HHHHHHxxxxxxxxxLLLLLLLLLLLLLLL
    // ST instructions:               ^     ^        ^    (T=0,6,15)

    volatile uint8_t next, bit;

    hi   = *port |  pinMask;
    lo   = *port & ~pinMask;
    next = lo;
    bit  = 8;

    asm volatile (
        "head30:"                  "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               // Clk  Pseudocode    (T =  0)
                                   "st   %a[port], %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     // 2    PORT = hi     (T =  2)
                                                             "sbrc %[byte] , 7"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           // 1-2  if(b & 128)
                                                                                       "mov  %[next], %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  // 0-1   next = hi    (T =  4)
                                                                                                                "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        // 2    nop nop       (T =  6)
                                                                                                                                          "st   %a[port], %[next]"  "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // 2    PORT = next   (T =  8)
                                                                                                                                                                    "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    // 2    nop nop       (T = 10)
                                                                                                                                                                                              "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 2    nop nop       (T = 12)
                                                                                                                                                                                                                        "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                // 2    nop nop       (T = 14)
                                                                                                                                                                                                                                                  "nop"                     "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                      // 1    nop           (T = 15)
                                                                                                                                                                                                                                                                            "st   %a[port], %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                            // 2    PORT = lo     (T = 17)
                                                                                                                                                                                                                                                                                                      "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                  // 2    nop nop       (T = 19)
                                                                                                                                                                                                                                                                                                                                "dec  %[bit]"             "\n\t"                                                                                                                                                                                                                                                                                                                        // 1    bit--         (T = 20)
                                                                                                                                                                                                                                                                                                                                                          "breq nextbyte30"         "\n\t"                                                                                                                                                                                                                                                                                              // 1-2  if(bit == 0)
                                                                                                                                                                                                                                                                                                                                                                                    "rol  %[byte]"            "\n\t"                                                                                                                                                                                                                                                                    // 1    b <<= 1       (T = 22)
                                                                                                                                                                                                                                                                                                                                                                                                              "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                          // 2    nop nop       (T = 24)
                                                                                                                                                                                                                                                                                                                                                                                                                                        "rjmp .+0"                "\n\t"                                                                                                                                                                                                                // 2    nop nop       (T = 26)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "rjmp .+0"                "\n\t"                                                                                                                                                                                      // 2    nop nop       (T = 28)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "rjmp head30"             "\n\t"                                                                                                                                                            // 2    -> head30 (next bit out)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "nextbyte30:"              "\n\t"                                                                                                                                 //                    (T = 22)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "nop"                     "\n\t"                                                                                                       // 1    nop           (T = 23)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "ldi  %[bit]  , 8"        "\n\t"                                                                             // 1    bit = 8       (T = 24)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "ld   %[byte] , %a[ptr]+" "\n\t"                                                   // 2    b = *ptr++    (T = 26)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "sbiw %[count], 1"        "\n\t"                         // 2    i--           (T = 28)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "brne head30"             "\n" // 1-2  if(i != 0) -> (next byte)
        :[port]  "+e" (port),
        [byte]  "+r" (b),
        [bit]   "+r" (bit),
        [next]  "+r" (next),
        [count] "+w" (i)
        :[hi]     "r" (hi),
        [lo]     "r" (lo),
        [ptr]    "e" (ptr));
}
#endif // NEO_KHZ400

    // 16 MHz(ish) AVR --------------------------------------------------------
#elif (F_CPU >= 15400000UL) && (F_CPU <= 19000000L)

#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
    if (is800KHz) {
#endif // ifdef NEO_KHZ400

    // WS2811 and WS2812 have different hi/lo duty cycles; this is
    // similar but NOT an exact copy of the prior 400-on-8 code.

    // 20 inst. clocks per bit: HHHHHxxxxxxxxLLLLLLL
    // ST instructions:         ^   ^        ^       (T=0,5,13)

    volatile uint8_t next, bit;

    hi   = *port |  pinMask;
    lo   = *port & ~pinMask;
    next = lo;
    bit  = 8;

    asm volatile (
        "head20:"                   "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     // Clk  Pseudocode    (T =  0)
                                    "st   %a[port],  %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 2    PORT = hi     (T =  2)
                                                               "sbrc %[byte],  7"         "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               // 1-2  if(b & 128)
                                                                                          "mov  %[next], %[hi]"     "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     // 0-1   next = hi    (T =  4)
                                                                                                                    "dec  %[bit]"              "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 1    bit--         (T =  5)
                                                                                                                                               "st   %a[port],  %[next]"  "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                               // 2    PORT = next   (T =  7)
                                                                                                                                                                          "mov  %[next] ,  %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                    // 1    next = lo     (T =  8)
                                                                                                                                                                                                     "breq nextbyte20"          "\n\t"                                                                                                                                                                                                                                                                                                                                                                                         // 1-2  if(bit == 0) (from dec above)
                                                                                                                                                                                                                                "rol  %[byte]"             "\n\t"                                                                                                                                                                                                                                                                                                                                                              // 1    b <<= 1       (T = 10)
                                                                                                                                                                                                                                                           "rjmp .+0"                 "\n\t"                                                                                                                                                                                                                                                                                                                                   // 2    nop nop       (T = 12)
                                                                                                                                                                                                                                                                                      "nop"                      "\n\t"                                                                                                                                                                                                                                                                                                        // 1    nop           (T = 13)
                                                                                                                                                                                                                                                                                                                 "st   %a[port],  %[lo]"    "\n\t"                                                                                                                                                                                                                                                                             // 2    PORT = lo     (T = 15)
                                                                                                                                                                                                                                                                                                                                            "nop"                      "\n\t"                                                                                                                                                                                                                                                  // 1    nop           (T = 16)
                                                                                                                                                                                                                                                                                                                                                                       "rjmp .+0"                 "\n\t"                                                                                                                                                                                                                       // 2    nop nop       (T = 18)
                                                                                                                                                                                                                                                                                                                                                                                                  "rjmp head20"              "\n\t"                                                                                                                                                                                            // 2    -> head20 (next bit out)
                                                                                                                                                                                                                                                                                                                                                                                                                             "nextbyte20:"               "\n\t"                                                                                                                                                                //                    (T = 10)
                                                                                                                                                                                                                                                                                                                                                                                                                                                         "ldi  %[bit]  ,  8"        "\n\t"                                                                                                                                     // 1    bit = 8       (T = 11)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "ld   %[byte] ,  %a[ptr]+" "\n\t"                                                                                                          // 2    b = *ptr++    (T = 13)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "st   %a[port], %[lo]"     "\n\t"                                                                               // 2    PORT = lo     (T = 15)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "nop"                      "\n\t"                                                    // 1    nop           (T = 16)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "sbiw %[count], 1"         "\n\t"                         // 2    i--           (T = 18)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "brne head20"             "\n" // 2    if(i != 0) -> (next byte)
        :[port]  "+e" (port),
        [byte]  "+r" (b),
        [bit]   "+r" (bit),
        [next]  "+r" (next),
        [count] "+w" (i)
        :[ptr]    "e" (ptr),
        [hi]     "r" (hi),
        [lo]     "r" (lo));

#ifdef NEO_KHZ400
} else { // 400 KHz
    // The 400 KHz clock on 16 MHz MCU is the most 'relaxed' version.

    // 40 inst. clocks per bit: HHHHHHHHxxxxxxxxxxxxLLLLLLLLLLLLLLLLLLLL
    // ST instructions:         ^       ^           ^         (T=0,8,20)

    volatile uint8_t next, bit;

    hi   = *port |  pinMask;
    lo   = *port & ~pinMask;
    next = lo;
    bit  = 8;

    asm volatile (
        "head40:"                  "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               // Clk  Pseudocode    (T =  0)
                                   "st   %a[port], %[hi]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     // 2    PORT = hi     (T =  2)
                                                             "sbrc %[byte] , 7"        "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           // 1-2  if(b & 128)
                                                                                       "mov  %[next] , %[hi]"   "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  // 0-1   next = hi    (T =  4)
                                                                                                                "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        // 2    nop nop       (T =  6)
                                                                                                                                          "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // 2    nop nop       (T =  8)
                                                                                                                                                                    "st   %a[port], %[next]"  "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    // 2    PORT = next   (T = 10)
                                                                                                                                                                                              "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 2    nop nop       (T = 12)
                                                                                                                                                                                                                        "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                // 2    nop nop       (T = 14)
                                                                                                                                                                                                                                                  "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      // 2    nop nop       (T = 16)
                                                                                                                                                                                                                                                                            "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            // 2    nop nop       (T = 18)
                                                                                                                                                                                                                                                                                                      "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  // 2    nop nop       (T = 20)
                                                                                                                                                                                                                                                                                                                                "st   %a[port], %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        // 2    PORT = lo     (T = 22)
                                                                                                                                                                                                                                                                                                                                                          "nop"                     "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              // 1    nop           (T = 23)
                                                                                                                                                                                                                                                                                                                                                                                    "mov  %[next] , %[lo]"    "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    // 1    next = lo     (T = 24)
                                                                                                                                                                                                                                                                                                                                                                                                              "dec  %[bit]"             "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                                          // 1    bit--         (T = 25)
                                                                                                                                                                                                                                                                                                                                                                                                                                        "breq nextbyte40"         "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                                                // 1-2  if(bit == 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "rol  %[byte]"            "\n\t"                                                                                                                                                                                                                                                                                                                                                                                                      // 1    b <<= 1       (T = 27)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "nop"                     "\n\t"                                                                                                                                                                                                                                                                                                                                                                            // 1    nop           (T = 28)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                                                  // 2    nop nop       (T = 30)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                                                        // 2    nop nop       (T = 32)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                                              // 2    nop nop       (T = 34)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                                                    // 2    nop nop       (T = 36)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "rjmp .+0"                "\n\t"                                                                                                                                                                                                                                          // 2    nop nop       (T = 38)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "rjmp head40"             "\n\t"                                                                                                                                                                                                                // 2    -> head40 (next bit out)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "nextbyte40:"              "\n\t"                                                                                                                                                                                     //                    (T = 27)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "ldi  %[bit]  , 8"        "\n\t"                                                                                                                                                           // 1    bit = 8       (T = 28)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "ld   %[byte] , %a[ptr]+" "\n\t"                                                                                                                                 // 2    b = *ptr++    (T = 30)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "rjmp .+0"                "\n\t"                                                                                                       // 2    nop nop       (T = 32)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "st   %a[port], %[lo]"    "\n\t"                                                                             // 2    PORT = lo     (T = 34)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "rjmp .+0"                "\n\t"                                                   // 2    nop nop       (T = 36)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "sbiw %[count], 1"        "\n\t"                         // 2    i--           (T = 38)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "brne head40"             "\n" // 1-2  if(i != 0) -> (next byte)
        :[port]  "+e" (port),
        [byte]  "+r" (b),
        [bit]   "+r" (bit),
        [next]  "+r" (next),
        [count] "+w" (i)
        :[ptr]    "e" (ptr),
        [hi]     "r" (hi),
        [lo]     "r" (lo));
}
#endif // NEO_KHZ400

#else // if (F_CPU >= 7400000UL) && (F_CPU <= 9500000UL)
 #error "CPU SPEED NOT SUPPORTED"
#endif // end F_CPU ifdefs on __AVR__

    // END AVR ----------------------------------------------------------------


#elif defined(__arm__)

    // ARM MCUs -- Teensy 3.0, 3.1, LC, Arduino Due ---------------------------

#if defined(TEENSYDUINO) && defined(KINETISK) // Teensy 3.0, 3.1, 3.2, 3.5, 3.6
#define CYCLES_800_T0H  (F_CPU / 4000000)
#define CYCLES_800_T1H  (F_CPU / 1250000)
#define CYCLES_800      (F_CPU /  800000)
#define CYCLES_400_T0H  (F_CPU / 2000000)
#define CYCLES_400_T1H  (F_CPU /  833333)
#define CYCLES_400      (F_CPU /  400000)

    uint8_t* p = pixels,
           * end = p + numBytes, pix, mask;
    volatile uint8_t* set = portSetRegister(pin),
                    * clr = portClearRegister(pin);
    uint32_t cyc;

    ARM_DEMCR    |= ARM_DEMCR_TRCENA;
    ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;

#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
    if (is800KHz) {
#endif // ifdef NEO_KHZ400
    cyc = ARM_DWT_CYCCNT + CYCLES_800;

    while (p < end) {
        pix = *p++;

        for (mask = 0x80; mask; mask >>= 1) {
            while (ARM_DWT_CYCCNT - cyc < CYCLES_800);
            cyc  = ARM_DWT_CYCCNT;
            *set = 1;
            if (pix & mask) {
                while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T1H);
            } else {
                while (ARM_DWT_CYCCNT - cyc < CYCLES_800_T0H);
            }
            *clr = 1;
        }
    }

    while (ARM_DWT_CYCCNT - cyc < CYCLES_800);
#ifdef NEO_KHZ400
} else { // 400 kHz bitstream
    cyc = ARM_DWT_CYCCNT + CYCLES_400;

    while (p < end) {
        pix = *p++;

        for (mask = 0x80; mask; mask >>= 1) {
            while (ARM_DWT_CYCCNT - cyc < CYCLES_400);
            cyc  = ARM_DWT_CYCCNT;
            *set = 1;
            if (pix & mask) {
                while (ARM_DWT_CYCCNT - cyc < CYCLES_400_T1H);
            } else {
                while (ARM_DWT_CYCCNT - cyc < CYCLES_400_T0H);
            }
            *clr = 1;
        }
    }

    while (ARM_DWT_CYCCNT - cyc < CYCLES_400);
}
#endif // NEO_KHZ400

#elif defined(TEENSYDUINO) && defined(__MKL26Z64__) // Teensy-LC

#if F_CPU == 48000000
    uint8_t* p = pixels,
           pix, count, dly,
           bitmask        = digitalPinToBitMask(pin);
    volatile uint8_t* reg = portSetRegister(pin);
    uint32_t num          = numBytes;
    asm volatile (
        "L%=_begin:"                      "\n\t"
                                          "ldrb  %[pix], [%[p], #0]"       "\n\t"
                                                                           "lsl   %[pix], #24"              "\n\t"
                                                                                                            "movs  %[count], #7"             "\n\t"
                                                                                                                                             "L%=_loop:"                       "\n\t"
                                                                                                                                                                               "lsl   %[pix], #1"               "\n\t"
                                                                                                                                                                                                                "bcs   L%=_loop_one"             "\n\t"
                                                                                                                                                                                                                                                 "L%=_loop_zero:"                 "\n\t"
                                                                                                                                                                                                                                                                                  "strb  %[bitmask], [%[reg], #0]" "\n\t"
                                                                                                                                                                                                                                                                                                                   "movs  %[dly], #4"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                    "L%=_loop_delay_T0H:"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                      "sub   %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                       "bne   L%=_loop_delay_T0H"       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                        "strb  %[bitmask], [%[reg], #4]" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "movs  %[dly], #13"              "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "L%=_loop_delay_T0L:"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "sub   %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "bne   L%=_loop_delay_T0L"       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "b     L%=_next"                 "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "L%=_loop_one:"                   "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "strb  %[bitmask], [%[reg], #0]" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "movs  %[dly], #13"              "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "L%=_loop_delay_T1H:"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "sub   %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "bne   L%=_loop_delay_T1H"       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "strb  %[bitmask], [%[reg], #4]" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "movs  %[dly], #4"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "L%=_loop_delay_T1L:"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "sub   %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "bne   L%=_loop_delay_T1L"       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "nop"                            "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "L%=_next:"                       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "sub   %[count], #1"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "bne   L%=_loop"                 "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "lsl   %[pix], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "bcs   L%=_last_one"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "L%=_last_zero:"                  "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "strb  %[bitmask], [%[reg], #0]" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "movs  %[dly], #4"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "L%=_last_delay_T0H:"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "sub   %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "bne   L%=_last_delay_T0H"       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "strb  %[bitmask], [%[reg], #4]" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "movs  %[dly], #10"              "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              "L%=_last_delay_T0L:"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "sub   %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "bne   L%=_last_delay_T0L"       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "b     L%=_repeat"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "L%=_last_one:"                   "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "strb  %[bitmask], [%[reg], #0]" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "movs  %[dly], #13"              "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "L%=_last_delay_T1H:"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "sub   %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          "bne   L%=_last_delay_T1H"       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "strb  %[bitmask], [%[reg], #4]" "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            "movs  %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "L%=_last_delay_T1L:"             "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "sub   %[dly], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "bne   L%=_last_delay_T1L"       "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "nop"                            "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  "L%=_repeat:"                     "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    "add   %[p], #1"                 "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "sub   %[num], #1"               "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      "bne   L%=_begin"                "\n\t"
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "L%=_done:"                       "\n\t"
        :[p]       "+r"  (p),
        [pix]     "=&r" (pix),
        [count]   "=&r" (count),
        [dly]     "=&r" (dly),
        [num]     "+r"  (num)
        :[bitmask] "r"   (bitmask),
        [reg]     "r"   (reg)
        );
#else // if F_CPU == 48000000
#error "Sorry, only 48 MHz is supported, please set Tools > CPU Speed to 48 MHz"
#endif // F_CPU == 48000000

    // Begin of support for nRF52 based boards  -------------------------

#elif defined(NRF52) || defined(NRF52_SERIES)
    // [[[Begin of the Neopixel NRF52 EasyDMA implementation
    //                                    by the Hackerspace San Salvador]]]
    // This technique uses the PWM peripheral on the NRF52. The PWM uses the
    // EasyDMA feature included on the chip. This technique loads the duty
    // cycle configuration for each cycle when the PWM is enabled. For this
    // to work we need to store a 16 bit configuration for each bit of the
    // RGB(W) values in the pixel buffer.
    // Comparator values for the PWM were hand picked and are guaranteed to
    // be 100% organic to preserve freshness and high accuracy. Current
    // parameters are:
    //   * PWM Clock: 16Mhz
    //   * Minimum step time: 62.5ns
    //   * Time for zero in high (T0H): 0.31ms
    //   * Time for one in high (T1H): 0.75ms
    //   * Cycle time:  1.25us
    //   * Frequency: 800Khz
    // For 400Khz we just double the calculated times.
    // ---------- BEGIN Constants for the EasyDMA implementation -----------
    // The PWM starts the duty cycle in LOW. To start with HIGH we
    // need to set the 15th bit on each register.

    // WS2812 (rev A) timing is 0.35 and 0.7us
    // #define MAGIC_T0H               5UL | (0x8000) // 0.3125us
    // #define MAGIC_T1H              12UL | (0x8000) // 0.75us

    // WS2812B (rev B) timing is 0.4 and 0.8 us
#define MAGIC_T0H               6UL | (0x8000)  // 0.375us
#define MAGIC_T1H              13UL | (0x8000)  // 0.8125us

    // WS2811 (400 khz) timing is 0.5 and 1.2
#define MAGIC_T0H_400KHz        8UL  | (0x8000) // 0.5us
#define MAGIC_T1H_400KHz        19UL | (0x8000) // 1.1875us

    // For 400Khz, we double value of CTOPVAL
#define CTOPVAL                20UL             // 1.25us
#define CTOPVAL_400KHz         40UL             // 2.5us

    // ---------- END Constants for the EasyDMA implementation -------------
    //
    // If there is no device available an alternative cycle-counter
    // implementation is tried.
    // The nRF52 runs with a fixed clock of 64Mhz. The alternative
    // implementation is the same as the one used for the Teensy 3.0/1/2 but
    // with the Nordic SDK HAL & registers syntax.
    // The number of cycles was hand picked and is guaranteed to be 100%
    // organic to preserve freshness and high accuracy.
    // ---------- BEGIN Constants for cycle counter implementation ---------
#define CYCLES_800_T0H  18  // ~0.36 uS
#define CYCLES_800_T1H  41  // ~0.76 uS
#define CYCLES_800      71  // ~1.25 uS

#define CYCLES_400_T0H  26  // ~0.50 uS
#define CYCLES_400_T1H  70  // ~1.26 uS
#define CYCLES_400      156 // ~2.50 uS
    // ---------- END of Constants for cycle counter implementation --------

    // To support both the SoftDevice + Neopixels we use the EasyDMA
    // feature from the NRF25. However this technique implies to
    // generate a pattern and store it on the memory. The actual
    // memory used in bytes corresponds to the following formula:
    //              totalMem = numBytes*8*2+(2*2)
    // The two additional bytes at the end are needed to reset the
    // sequence.
    //
    // If there is not enough memory, we will fall back to cycle counter
    // using DWT
    uint32_t  pattern_size   = numBytes*8*sizeof(uint16_t)+2*sizeof(uint16_t);
    uint16_t* pixels_pattern = NULL;

    NRF_PWM_Type* pwm = NULL;

    // Try to find a free PWM device, which is not enabled
    // and has no connected pins
    NRF_PWM_Type* PWM[] = {
        NRF_PWM0, NRF_PWM1, NRF_PWM2
#ifdef NRF_PWM3
        ,         NRF_PWM3
#endif // ifdef NRF_PWM3
    };

    for (int device = 0; device < (sizeof(PWM)/sizeof(PWM[0])); device++) {
        if ((PWM[device]->ENABLE == 0)                            &&
            (PWM[device]->PSEL.OUT[0] & PWM_PSEL_OUT_CONNECT_Msk) &&
            (PWM[device]->PSEL.OUT[1] & PWM_PSEL_OUT_CONNECT_Msk) &&
            (PWM[device]->PSEL.OUT[2] & PWM_PSEL_OUT_CONNECT_Msk) &&
            (PWM[device]->PSEL.OUT[3] & PWM_PSEL_OUT_CONNECT_Msk)
            ) {
            pwm = PWM[device];
            break;
        }
    }

    // only malloc if there is PWM device available
    if (pwm != NULL) {
    #ifdef ARDUINO_NRF52_ADAFRUIT // use thread-safe malloc
        pixels_pattern = (uint16_t*)rtos_malloc(pattern_size);
    #else // ifdef ARDUINO_NRF52_ADAFRUIT
        pixels_pattern = (uint16_t*)malloc(pattern_size);
    #endif // ifdef ARDUINO_NRF52_ADAFRUIT
    }

    // Use the identified device to choose the implementation
    // If a PWM device is available use DMA
    if ((pixels_pattern != NULL) && (pwm != NULL)) {
        uint16_t pos = 0; // bit position

        for (uint16_t n = 0; n<numBytes; n++) {
            uint8_t pix = pixels[n];

            for (uint8_t mask = 0x80; mask>0; mask >>= 1) {
        #ifdef NEO_KHZ400
                if (!is800KHz) {
                    pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H_400KHz : MAGIC_T0H_400KHz;
                } else
        #endif // ifdef NEO_KHZ400
                {
                    pixels_pattern[pos] = (pix & mask) ? MAGIC_T1H : MAGIC_T0H;
                }

                pos++;
            }
        }

        // Zero padding to indicate the end of que sequence
        pixels_pattern[pos++] = 0 | (0x8000); // Seq end
        pixels_pattern[pos++] = 0 | (0x8000); // Seq end

        // Set the wave mode to count UP
        pwm->MODE = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos);

        // Set the PWM to use the 16MHz clock
        pwm->PRESCALER = (PWM_PRESCALER_PRESCALER_DIV_1 << PWM_PRESCALER_PRESCALER_Pos);

        // Setting of the maximum count
        // but keeping it on 16Mhz allows for more granularity just
        // in case someone wants to do more fine-tuning of the timing.
#ifdef NEO_KHZ400
        if (!is800KHz) {
            pwm->COUNTERTOP = (CTOPVAL_400KHz << PWM_COUNTERTOP_COUNTERTOP_Pos);
        } else
#endif // ifdef NEO_KHZ400
        {
            pwm->COUNTERTOP = (CTOPVAL << PWM_COUNTERTOP_COUNTERTOP_Pos);
        }

        // Disable loops, we want the sequence to repeat only once
        pwm->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos);

        // On the "Common" setting the PWM uses the same pattern for the
        // for supported sequences. The pattern is stored on half-word
        // of 16bits
        pwm->DECODER = (PWM_DECODER_LOAD_Common << PWM_DECODER_LOAD_Pos) |
                       (PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);

        // Pointer to the memory storing the patter
        pwm->SEQ[0].PTR = (uint32_t)(pixels_pattern) << PWM_SEQ_PTR_PTR_Pos;

        // Calculation of the number of steps loaded from memory.
        pwm->SEQ[0].CNT = (pattern_size/sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos;

        // The following settings are ignored with the current config.
        pwm->SEQ[0].REFRESH  = 0;
        pwm->SEQ[0].ENDDELAY = 0;

        // The Neopixel implementation is a blocking algorithm. DMA
        // allows for non-blocking operation. To "simulate" a blocking
        // operation we enable the interruption for the end of sequence
        // and block the execution thread until the event flag is set by
        // the peripheral.
        //    pwm->INTEN |= (PWM_INTEN_SEQEND0_Enabled<<PWM_INTEN_SEQEND0_Pos);

        // PSEL must be configured before enabling PWM
        pwm->PSEL.OUT[0] = g_ADigitalPinMap[pin];

        // Enable the PWM
        pwm->ENABLE = 1;

        // After all of this and many hours of reading the documentation
        // we are ready to start the sequence...
        pwm->EVENTS_SEQEND[0]  = 0;
        pwm->TASKS_SEQSTART[0] = 1;

        // But we have to wait for the flag to be set.
        while (!pwm->EVENTS_SEQEND[0])
        {
      #ifdef ARDUINO_NRF52_ADAFRUIT
            yield();
      #endif // ifdef ARDUINO_NRF52_ADAFRUIT
        }

        // Before leave we clear the flag for the event.
        pwm->EVENTS_SEQEND[0] = 0;

        // We need to disable the device and disconnect
        // all the outputs before leave or the device will not
        // be selected on the next call.
        // TODO: Check if disabling the device causes performance issues.
        pwm->ENABLE = 0;

        pwm->PSEL.OUT[0] = 0xFFFFFFFFUL;

    #ifdef ARDUINO_NRF52_ADAFRUIT // use thread-safe free
        rtos_free(pixels_pattern);
    #else // ifdef ARDUINO_NRF52_ADAFRUIT
        free(pixels_pattern);
    #endif // ifdef ARDUINO_NRF52_ADAFRUIT
    } // End of DMA implementation
    // ---------------------------------------------------------------------
    else {
        // Fall back to DWT
    #ifdef ARDUINO_NRF52_ADAFRUIT
        // Bluefruit Feather 52 uses freeRTOS
        // Critical Section is used since it does not block SoftDevice execution
        taskENTER_CRITICAL();
    #elif defined(NRF52_DISABLE_INT)
        // If you are using the Bluetooth SoftDevice we advise you to not disable
        // the interrupts. Disabling the interrupts even for short periods of time
        // causes the SoftDevice to stop working.
        // Disable the interrupts only in cases where you need high performance for
        // the LEDs and if you are not using the EasyDMA feature.
        __disable_irq();
    #endif // ifdef ARDUINO_NRF52_ADAFRUIT

        NRF_GPIO_Type* nrf_port = (NRF_GPIO_Type*)digitalPinToPort(pin);
        uint32_t pinMask        = digitalPinToBitMask(pin);

        uint32_t CYCLES_X00     = CYCLES_800;
        uint32_t CYCLES_X00_T1H = CYCLES_800_T1H;
        uint32_t CYCLES_X00_T0H = CYCLES_800_T0H;

#ifdef NEO_KHZ400
        if (!is800KHz)
        {
            CYCLES_X00     = CYCLES_400;
            CYCLES_X00_T1H = CYCLES_400_T1H;
            CYCLES_X00_T0H = CYCLES_400_T0H;
        }
#endif // ifdef NEO_KHZ400

        // Enable DWT in debug core
        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CTRL        |= DWT_CTRL_CYCCNTENA_Msk;

        // Tries to re-send the frame if is interrupted by the SoftDevice.
        while (1) {
            uint8_t* p = pixels;

            uint32_t cycStart = DWT->CYCCNT;
            uint32_t cyc      = 0;

            for (uint16_t n = 0; n<numBytes; n++) {
                uint8_t pix = *p++;

                for (uint8_t mask = 0x80; mask; mask >>= 1) {
                    while (DWT->CYCCNT - cyc < CYCLES_X00);
                    cyc = DWT->CYCCNT;

                    nrf_port->OUTSET |= pinMask;

                    if (pix & mask) {
                        while (DWT->CYCCNT - cyc < CYCLES_X00_T1H);
                    } else {
                        while (DWT->CYCCNT - cyc < CYCLES_X00_T0H);
                    }

                    nrf_port->OUTCLR |= pinMask;
                }
            }

            while (DWT->CYCCNT - cyc < CYCLES_X00);


            // If total time longer than 25%, resend the whole data.
            // Since we are likely to be interrupted by SoftDevice
            if ((DWT->CYCCNT - cycStart) < (8*numBytes*((CYCLES_X00*5)/4))) {
                break;
            }

            // re-send need 300us delay
            delayMicroseconds(300);
        }

        // Enable interrupts again
    #ifdef ARDUINO_NRF52_ADAFRUIT
        taskEXIT_CRITICAL();
    #elif defined(NRF52_DISABLE_INT)
        __enable_irq();
    #endif // ifdef ARDUINO_NRF52_ADAFRUIT
    }
    // END of NRF52 implementation

#elif defined(__SAMD21E17A__) || defined(__SAMD21G18A__)  || defined(__SAMD21E18A__) || defined(__SAMD21J18A__) // Arduino Zero, Gemma/Trinket M0, SODAQ Autonomo and others
    // Tried this with a timer/counter, couldn't quite get adequate
    // resolution. So yay, you get a load of goofball NOPs...

    uint8_t* ptr, * end, p, bitMask, portNum;
    uint32_t pinMask;

    portNum =  g_APinDescription[pin].ulPort;
    pinMask =  1ul << g_APinDescription[pin].ulPin;
    ptr     =  pixels;
    end     =  ptr + numBytes;
    p       = *ptr++;
    bitMask =  0x80;

    volatile uint32_t* set = &(PORT->Group[portNum].OUTSET.reg),
                     * clr = &(PORT->Group[portNum].OUTCLR.reg);

#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
    if (is800KHz) {
#endif // ifdef NEO_KHZ400

    for (;;) {
        *set = pinMask;
        asm ("nop; nop; nop; nop; nop; nop; nop; nop;");
        if (p & bitMask) {
            asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop;");
            *clr = pinMask;
        } else {
            *clr = pinMask;
            asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop;");
        }
        if (bitMask >>= 1) {
            asm ("nop; nop; nop; nop; nop; nop; nop; nop; nop;");
        } else {
            if (ptr >= end) break;
            p       = *ptr++;
            bitMask = 0x80;
        }
    }
#ifdef NEO_KHZ400
} else { // 400 KHz bitstream
    for (;;) {
        *set = pinMask;
        asm ("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
        if (p & bitMask) {
            asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop;");
            *clr = pinMask;
        } else {
            *clr = pinMask;
            asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop;");
        }
        asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
             "nop; nop; nop; nop; nop; nop; nop; nop;"
             "nop; nop; nop; nop; nop; nop; nop; nop;"
             "nop; nop; nop; nop; nop; nop; nop; nop;");
        if (bitMask >>= 1) {
            asm ("nop; nop; nop; nop; nop; nop; nop;");
        } else {
            if (ptr >= end) break;
            p       = *ptr++;
            bitMask = 0x80;
        }
    }
}
#endif // ifdef NEO_KHZ400

#elif defined(__SAMD51__) // M4

    uint8_t* ptr, * end, p, bitMask, portNum, bit;
    uint32_t pinMask;

    portNum =  g_APinDescription[pin].ulPort;
    pinMask =  1ul << g_APinDescription[pin].ulPin;
    ptr     =  pixels;
    end     =  ptr + numBytes;
    p       = *ptr++;
    bitMask =  0x80;

    volatile uint32_t* set = &(PORT->Group[portNum].OUTSET.reg),
                     * clr = &(PORT->Group[portNum].OUTCLR.reg);

    // SAMD51 overclock-compatible timing is only a mild abomination.
    // It uses SysTick for a consistent clock reference regardless of
    // optimization / cache settings.  That's the good news.  The bad news,
    // since SysTick->VAL is a volatile type it's slow to access...and then,
    // with the SysTick interval that Arduino sets up (1 ms), this would
    // require a subtract and MOD operation for gauging elapsed time, and
    // all taken in combination that lacks adequate temporal resolution
    // for NeoPixel timing.  So a kind of horrible thing is done here...
    // since interrupts are turned off anyway and it's generally accepted
    // by now that we're gonna lose track of time in the NeoPixel lib,
    // the SysTick timer is reconfigured for a period matching the NeoPixel
    // bit timing (either 800 or 400 KHz) and we watch SysTick->VAL very
    // closely (just a threshold, no subtract or MOD or anything) and that
    // seems to work just well enough.  When finished, the SysTick
    // peripheral is set back to its original state.

    uint32_t t0, t1, top, ticks,
             saveLoad = SysTick->LOAD, saveVal = SysTick->VAL;

#ifdef NEO_KHZ400                               // 800 KHz check needed only if 400 KHz support enabled
    if (is800KHz) {
#endif // ifdef NEO_KHZ400
    top =       (uint32_t)(F_CPU * 0.00000125); // Bit hi + lo = 1.25 uS
    t0  = top - (uint32_t)(F_CPU * 0.00000040); // 0 = 0.4 uS hi
    t1  = top - (uint32_t)(F_CPU * 0.00000080); // 1 = 0.8 uS hi
#ifdef NEO_KHZ400
} else {                                        // 400 KHz bitstream
    top =       (uint32_t)(F_CPU * 0.00000250); // Bit hi + lo = 2.5 uS
    t0  = top - (uint32_t)(F_CPU * 0.00000050); // 0 = 0.5 uS hi
    t1  = top - (uint32_t)(F_CPU * 0.00000120); // 1 = 1.2 uS hi
}
#endif // ifdef NEO_KHZ400

    SysTick->LOAD = top;                 // Config SysTick for NeoPixel bit freq
    SysTick->VAL  = top;                 // Set to start value (counts down)
    (void)SysTick->VAL;                  // Dummy read helps sync up 1st bit

    for (;;) {
        *set  = pinMask;                 // Set output high
        ticks = (p & bitMask) ? t1 : t0; // SysTick threshold,

        while (SysTick->VAL > ticks);    // wait for it
        *clr = pinMask;                  // Set output low
        if (!(bitMask >>= 1)) {          // Next bit for this byte...done?
            if (ptr >= end) break;       // If last byte sent, exit loop
            p       = *ptr++;            // Fetch next byte
            bitMask = 0x80;              // Reset bitmask
        }

        while (SysTick->VAL <= ticks);   // Wait for rollover to 'top'
    }

    SysTick->LOAD = saveLoad;            // Restore SysTick rollover to 1 ms
    SysTick->VAL  = saveVal;             // Restore SysTick value

#elif defined(ARDUINO_STM32_FEATHER)     // FEATHER WICED (120MHz)

    // Tried this with a timer/counter, couldn't quite get adequate
    // resolution. So yay, you get a load of goofball NOPs...

    uint8_t* ptr, * end, p, bitMask;
    uint32_t pinMask;

    pinMask =  BIT(PIN_MAP[pin].gpio_bit);
    ptr     =  pixels;
    end     =  ptr + numBytes;
    p       = *ptr++;
    bitMask =  0x80;

    volatile uint16_t* set = &(PIN_MAP[pin].gpio_device->regs->BSRRL);
    volatile uint16_t* clr = &(PIN_MAP[pin].gpio_device->regs->BSRRH);

#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
    if (is800KHz) {
#endif // ifdef NEO_KHZ400

    for (;;) {
        if (p & bitMask) { // ONE
            // High 800ns
            *set = pinMask;
            asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop;");
            // Low 450ns
            *clr = pinMask;
            asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop;");
        } else { // ZERO
            // High 400ns
            *set = pinMask;
            asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop;");
            // Low 850ns
            *clr = pinMask;
            asm ("nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop; nop; nop; nop; nop;"
                 "nop; nop; nop; nop;");
        }
        if (bitMask >>= 1) {
            // Move on to the next pixel
            asm ("nop;");
        } else {
            if (ptr >= end) break;
            p       = *ptr++;
            bitMask = 0x80;
        }
    }
#ifdef NEO_KHZ400
} else { // 400 KHz bitstream
    // ToDo!
}
#endif // ifdef NEO_KHZ400

#elif defined(NRF51)
    uint8_t* p = pixels,
           pix, count, mask;
    int32_t num          = numBytes;
    unsigned int bitmask = (1 << g_ADigitalPinMap[pin]);
    // https://github.com/sandeepmistry/arduino-nRF5/blob/dc53980c8bac27898fca90d8ecb268e11111edc1/variants/BBCmicrobit/variant.cpp

    volatile unsigned int* reg = (unsigned int*)(0x50000000UL + 0x508);

    // https://github.com/sandeepmistry/arduino-nRF5/blob/dc53980c8bac27898fca90d8ecb268e11111edc1/cores/nRF5/SDK/components/device/nrf51.h
    // http://www.iot-programmer.com/index.php/books/27-micro-bit-iot-in-c/chapters-micro-bit-iot-in-c/47-micro-bit-iot-in-c-fast-memory-mapped-gpio?showall=1
    // https://github.com/Microsoft/pxt-neopixel/blob/master/sendbuffer.asm

    asm volatile (
        // "cpsid i" ; disable irq

        //    b .start
        "b  L%=_start"                    "\n\t"
        // .nextbit:               ;            C0
                                          "L%=_nextbit:"                    "\n\t"                                                                                                                                         // ;            C0
        //    str r1, [r3, #0]    ; pin := hi  C2
                                                                            "strb %[bitmask], [%[reg], #0]"   "\n\t"                                                                                                       // ; pin := hi  C2
        //    tst r6, r0          ;            C3
                                                                                                              "tst %[mask], %[pix]"             "\n\t"                                                                     //          ;            C3
        //    bne .islate         ;            C4
                                                                                                                                                "bne L%=_islate"                  "\n\t"                                   // ;            C4
        //    str r1, [r2, #0]    ; pin := lo  C6
                                                                                                                                                                                  "strb %[bitmask], [%[reg], #4]"   "\n\t" // ; pin := lo  C6
        // .islate:
                                                                                                                                                                                                                    "L%=_islate:"                     "\n\t"
        //    lsrs r6, r6, #1     ; r6 >>= 1   C7
                                                                                                                                                                                                                                                      "lsr %[mask], %[mask], #1"       "\n\t"                                   // ; r6 >>= 1   C7
        //    bne .justbit        ;            C8
                                                                                                                                                                                                                                                                                       "bne L%=_justbit"                 "\n\t" // ;            C8

        //    ; not just a bit - need new byte
        //    adds r4, #1         ; r4++       C9
                                                                                                                                                                                                                                                                                                                         "add %[p], #1"                   "\n\t"                                                                    // ; r4++       C9
        //    subs r5, #1         ; r5--       C10
                                                                                                                                                                                                                                                                                                                                                          "sub %[num], #1"                 "\n\t"                                   // ; r5--       C10
        //    bcc .stop           ; if (r5<0) goto .stop  C11
                                                                                                                                                                                                                                                                                                                                                                                           "bcc L%=_stop"                    "\n\t" // ; if (r5<0) goto .stop  C11
        // .start:
                                                                                                                                                                                                                                                                                                                                                                                                                             "L%=_start:"
        //    movs r6, #0x80      ; reset mask C12
                                                                                                                                                                                                                                                                                                                                                                                                                             "movs %[mask], #0x80"             "\n\t"                                                                                                                                                                                                                                               // ; reset mask C12
        //    nop                 ;            C13
                                                                                                                                                                                                                                                                                                                                                                                                                                                               "nop"                             "\n\t"                                                                                                                                                                                                             // ;            C13

        // .common:               ;             C13
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 "L%=_common:"                     "\n\t"                                                                                                                                                                           // ;            C13
        //    str r1, [r2, #0]   ; pin := lo   C15
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   "strb %[bitmask], [%[reg], #4]"   "\n\t"                                                                                                                                         // ; pin := lo  C15
        //    ; always re-load byte - it just fits with the cycles better this way
        //    ldrb r0, [r4, #0]  ; r0 := *r4   C17
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     "ldrb  %[pix], [%[p], #0]"        "\n\t"                                                                                                       // ; r0 := *r4   C17
        //    b .nextbit         ;             C20
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "b L%=_nextbit"                   "\n\t"                                                                     // ;             C20

        // .justbit: ; C10
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "L%=_justbit:"                    "\n\t"                                   // ; C10
        //    ; no nops, branch taken is already 3 cycles
        //    b .common ; C13
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "b L%=_common"                    "\n\t" // ; C13

        // .stop:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             "L%=_stop:"                       "\n\t"
        //    str r1, [r2, #0]   ; pin := lo
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               "strb %[bitmask], [%[reg], #4]"   "\n\t" // ; pin := lo
        //    cpsie i            ; enable irq

        :[p] "+r" (p),
        [pix] "=&r" (pix),
        [count] "=&r" (count),
        [mask] "=&r" (mask),
        [num] "+r" (num)
        :[bitmask] "r" (bitmask),
        [reg] "r" (reg)
        );

#elif defined(__SAM3X8E__) // Arduino Due

  #define SCALE      VARIANT_MCK / 2UL / 1000000UL
  #define INST       (2UL * F_CPU / VARIANT_MCK)
  #define TIME_800_0 ((int)(0.40 * SCALE + 0.5) - (5 * INST))
  #define TIME_800_1 ((int)(0.80 * SCALE + 0.5) - (5 * INST))
  #define PERIOD_800 ((int)(1.25 * SCALE + 0.5) - (5 * INST))
  #define TIME_400_0 ((int)(0.50 * SCALE + 0.5) - (5 * INST))
  #define TIME_400_1 ((int)(1.20 * SCALE + 0.5) - (5 * INST))
  #define PERIOD_400 ((int)(2.50 * SCALE + 0.5) - (5 * INST))

    int  pinMask, time0, time1, period, t;
    Pio* port;
    volatile WoReg* portSet, * portClear, * timeValue, * timeReset;
    uint8_t* p, * end, pix, mask;

    pmc_set_writeprotect(false);
    pmc_enable_periph_clk((uint32_t)TC3_IRQn);
    TC_Configure(TC1, 0,
                 TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK1);
    TC_Start(TC1, 0);

    pinMask   = g_APinDescription[pin].ulPin; // Don't 'optimize' these into
    port      = g_APinDescription[pin].pPort; // declarations above. Want to
    portSet   = &(port->PIO_SODR);            // burn a few cycles after
    portClear = &(port->PIO_CODR);            // starting timer to minimize
    timeValue = &(TC1->TC_CHANNEL[0].TC_CV);  // the initial 'while'.
    timeReset = &(TC1->TC_CHANNEL[0].TC_CCR);
    p         =  pixels;
    end       =  p + numBytes;
    pix       = *p++;
    mask      = 0x80;

#ifdef NEO_KHZ400 // 800 KHz check needed only if 400 KHz support enabled
    if (is800KHz) {
#endif // ifdef NEO_KHZ400
    time0  = TIME_800_0;
    time1  = TIME_800_1;
    period = PERIOD_800;
#ifdef NEO_KHZ400
} else { // 400 KHz bitstream
    time0  = TIME_400_0;
    time1  = TIME_400_1;
    period = PERIOD_400;
}
#endif // ifdef NEO_KHZ400

    for (t = time0;; t = time0) {
        if (pix & mask) t = time1;

        while (*timeValue < period);
        *portSet   = pinMask;
        *timeReset = TC_CCR_CLKEN | TC_CCR_SWTRG;

        while (*timeValue < t);
        *portClear = pinMask;
        if (!(mask >>= 1)) {      // This 'inside-out' loop logic utilizes
            if (p >= end) break;  // idle time to minimize inter-byte delays.
            pix  = *p++;
            mask = 0x80;
        }
    }

    while (*timeValue < period);  // Wait for last bit
    TC_Stop(TC1, 0);

#endif // end Due

    // END ARM ----------------------------------------------------------------


#elif defined(ESP8266) || defined(ESP32)

    // ESP8266 ----------------------------------------------------------------

    // ESP8266 show() is external to enforce ICACHE_RAM_ATTR execution
    espShow(pin, pixels, numBytes, is800KHz);

#elif defined(__ARDUINO_ARC__)

    // Arduino 101  -----------------------------------------------------------

#define NOPx7 { __builtin_arc_nop();\
                __builtin_arc_nop(); __builtin_arc_nop();\
                __builtin_arc_nop(); __builtin_arc_nop();\
                __builtin_arc_nop(); __builtin_arc_nop(); }

    PinDescription  * pindesc    = &g_APinDescription[pin];
    register uint32_t loop       = 8 * numBytes; // one loop to handle all bytes and all bits
    register uint8_t* p          = pixels;
    register uint32_t currByte   = (uint32_t)(*p);
    register uint32_t currBit    = 0x80 & currByte;
    register uint32_t bitCounter = 0;
    register uint32_t first      = 1;

    // The loop is unusual. Very first iteration puts all the way LOW to the wire -
    // constant LOW does not affect NEOPIXEL, so there is no visible effect displayed.
    // During that very first iteration CPU caches instructions in the loop.
    // Because of the caching process, "CPU slows down". NEOPIXEL pulse is very time sensitive
    // that's why we let the CPU cache first and we start regular pulse from 2nd iteration
    if (pindesc->ulGPIOType == SS_GPIO) {
        register uint32_t reg          = pindesc->ulGPIOBase + SS_GPIO_SWPORTA_DR;
        uint32_t reg_val               = __builtin_arc_lr((volatile uint32_t)reg);
        register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId);
        register uint32_t reg_bit_low  = reg_val & ~(1 << pindesc->ulGPIOId);

        loop += 1; // include first, special iteration

        while (loop--) {
            if (!first) {
                currByte <<= 1;
                bitCounter++;
            }

            // 1 is >550ns high and >450ns low; 0 is 200..500ns high and >450ns low
            __builtin_arc_sr(first ? reg_bit_low : reg_bit_high, (volatile uint32_t)reg);
            if (currBit) { // ~400ns HIGH (740ns overall)
                NOPx7
                    NOPx7
            }
            // ~340ns HIGH
            NOPx7
                    __builtin_arc_nop();

            // 820ns LOW; per spec, max allowed low here is 5000ns */
            __builtin_arc_sr(reg_bit_low, (volatile uint32_t)reg);
            NOPx7
                NOPx7

            if (bitCounter >= 8) {
                bitCounter = 0;
                currByte   = (uint32_t)(*++p);
            }

            currBit = 0x80 & currByte;
            first   = 0;
        }
    } else if (pindesc->ulGPIOType == SOC_GPIO) {
        register uint32_t reg          = pindesc->ulGPIOBase + SOC_GPIO_SWPORTA_DR;
        uint32_t reg_val               = MMIO_REG_VAL(reg);
        register uint32_t reg_bit_high = reg_val | (1 << pindesc->ulGPIOId);
        register uint32_t reg_bit_low  = reg_val & ~(1 << pindesc->ulGPIOId);

        loop += 1; // include first, special iteration

        while (loop--) {
            if (!first) {
                currByte <<= 1;
                bitCounter++;
            }
            MMIO_REG_VAL(reg) = first ? reg_bit_low : reg_bit_high;
            if (currBit) { // ~430ns HIGH (740ns overall)
                NOPx7
                NOPx7
                    __builtin_arc_nop();
            }
            // ~310ns HIGH
            NOPx7

            // 850ns LOW; per spec, max allowed low here is 5000ns */
                MMIO_REG_VAL(reg) = reg_bit_low;
            NOPx7
                NOPx7

            if (bitCounter >= 8) {
                bitCounter = 0;
                currByte   = (uint32_t)(*++p);
            }

            currBit = 0x80 & currByte;
            first   = 0;
        }
    }

#else // ifdef __AVR__
#error Architecture not supported
#endif // ifdef __AVR__


    // END ARCHITECTURE SELECT ------------------------------------------------

#if !(defined(NRF52) || defined(NRF52_SERIES))
    interrupts();
#endif // if !(defined(NRF52) || defined(NRF52_SERIES))

    endTime = micros(); // Save EOD time for latch on next call
}

/*!
   @brief   Set/change the NeoPixel output pin number. Previous pin,
           if any, is set to INPUT and the new pin is set to OUTPUT.
   @param   p  Arduino pin number (-1 = no pin).
 */
void NeoPixel::setPin(uint8_t p) {
    if (begun && (pin >= 0)) pinMode(pin, INPUT);
    pin = p;
    if (begun) {
        pinMode(p, OUTPUT);
        digitalWrite(p, LOW);
    }
#ifdef __AVR__
    port    = portOutputRegister(digitalPinToPort(p));
    pinMask = digitalPinToBitMask(p);
#endif // ifdef __AVR__
}

/*!
   @brief   Set a pixel's color using separate red, green and blue
           components. If using RGBW pixels, white will be set to 0.
   @param   n  Pixel index, starting from 0.
   @param   r  Red brightness, 0 = minimum (off), 255 = maximum.
   @param   g  Green brightness, 0 = minimum (off), 255 = maximum.
   @param   b  Blue brightness, 0 = minimum (off), 255 = maximum.
 */
void NeoPixel::setPixelColor(
    uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
    if (n < numLEDs) {
        if (brightness) { // See notes in setBrightness()
            r = (r * brightness) >> 8;
            g = (g * brightness) >> 8;
            b = (b * brightness) >> 8;
        }
        uint8_t* p;
        if (wOffset == rOffset) {        // Is an RGB-type strip
            p = &pixels[n * 3];          // 3 bytes per pixel
        } else {                         // Is a WRGB-type strip
            p          = &pixels[n * 4]; // 4 bytes per pixel
            p[wOffset] = 0;              // But only R,G,B passed -- set W to 0
        }
        p[rOffset] = r;                  // R,G,B always stored
        p[gOffset] = g;
        p[bOffset] = b;
    }
}

/*!
   @brief   Set a pixel's color using separate red, green, blue and white
           components (for RGBW NeoPixels only).
   @param   n  Pixel index, starting from 0.
   @param   r  Red brightness, 0 = minimum (off), 255 = maximum.
   @param   g  Green brightness, 0 = minimum (off), 255 = maximum.
   @param   b  Blue brightness, 0 = minimum (off), 255 = maximum.
   @param   w  White brightness, 0 = minimum (off), 255 = maximum, ignored
              if using RGB pixels.
 */
void NeoPixel::setPixelColor(
    uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
    if (n < numLEDs) {
        if (brightness) { // See notes in setBrightness()
            r = (r * brightness) >> 8;
            g = (g * brightness) >> 8;
            b = (b * brightness) >> 8;
            w = (w * brightness) >> 8;
        }
        uint8_t* p;
        if (wOffset == rOffset) {        // Is an RGB-type strip
            p = &pixels[n * 3];          // 3 bytes per pixel (ignore W)
        } else {                         // Is a WRGB-type strip
            p          = &pixels[n * 4]; // 4 bytes per pixel
            p[wOffset] = w;              // Store W
        }
        p[rOffset] = r;                  // Store R,G,B
        p[gOffset] = g;
        p[bOffset] = b;
    }
}

/*!
   @brief   Set a pixel's color using a 32-bit 'packed' RGB or RGBW value.
   @param   n  Pixel index, starting from 0.
   @param   c  32-bit color value. Most significant byte is white (for RGBW
              pixels) or ignored (for RGB pixels), next is red, then green,
              and least significant byte is blue.
 */
void NeoPixel::setPixelColor(uint16_t n, uint32_t c) {
    if (n < numLEDs) {
        uint8_t* p,
               r = (uint8_t)(c >> 16),
               g = (uint8_t)(c >>  8),
               b = (uint8_t)c;
        if (brightness) { // See notes in setBrightness()
            r = (r * brightness) >> 8;
            g = (g * brightness) >> 8;
            b = (b * brightness) >> 8;
        }
        if (wOffset == rOffset) {
            p = &pixels[n * 3];
        } else {
            p = &pixels[n * 4];
            uint8_t w = (uint8_t)(c >> 24);
            p[wOffset] = brightness ? ((w * brightness) >> 8) : w;
        }
        p[rOffset] = r;
        p[gOffset] = g;
        p[bOffset] = b;
    }
}

/*!
   @brief   Fill all or part of the NeoPixel strip with a color.
   @param   c      32-bit color value. Most significant byte is white (for
                  RGBW pixels) or ignored (for RGB pixels), next is red,
                  then green, and least significant byte is blue. If all
                  arguments are unspecified, this will be 0 (off).
   @param   first  Index of first pixel to fill, starting from 0. Must be
                  in-bounds, no clipping is performed. 0 if unspecified.
   @param   count  Number of pixels to fill, as a positive value. Passing
                  0 or leaving unspecified will fill to end of strip.
 */
void NeoPixel::fill(uint32_t c, uint16_t first, uint16_t count) {
    uint16_t i, end;

    if (first >= numLEDs) {
        return; // If first LED is past end of strip, nothing to do
    }

    // Calculate the index ONE AFTER the last pixel to fill
    if (count == 0) {
        // Fill to end of strip
        end = numLEDs;
    } else {
        // Ensure that the loop won't go past the last pixel
        end = first + count;
        if (end > numLEDs) end = numLEDs;
    }

    for (i = first; i < end; i++) {
        this->setPixelColor(i, c);
    }
}

/*!
   @brief   Convert hue, saturation and value into a packed 32-bit RGB color
           that can be passed to setPixelColor() or other RGB-compatible
           functions.
   @param   hue  An unsigned 16-bit value, 0 to 65535, representing one full
                loop of the color wheel, which allows 16-bit hues to "roll
                over" while still doing the expected thing (and allowing
                more precision than the wheel() function that was common to
                prior NeoPixel examples).
   @param   sat  Saturation, 8-bit value, 0 (min or pure grayscale) to 255
                (max or pure hue). Default of 255 if unspecified.
   @param   val  Value (brightness), 8-bit value, 0 (min / black / off) to
                255 (max or full brightness). Default of 255 if unspecified.
   @return  Packed 32-bit RGB with the most significant byte set to 0 -- the
           white element of WRGB pixels is NOT utilized. Result is linearly
           but not perceptually correct, so you may want to pass the result
           through the gamma32() function (or your own gamma-correction
           operation) else colors may appear washed out. This is not done
           automatically by this function because coders may desire a more
           refined gamma-correction function than the simplified
           one-size-fits-all operation of gamma32(). Diffusing the LEDs also
           really seems to help when using low-saturation colors.
 */
uint32_t NeoPixel::ColorHSV(uint16_t hue, uint8_t sat, uint8_t val) {
    uint8_t r, g, b;

    // Remap 0-65535 to 0-1529. Pure red is CENTERED on the 64K rollover;
    // 0 is not the start of pure red, but the midpoint...a few values above
    // zero and a few below 65536 all yield pure red (similarly, 32768 is the
    // midpoint, not start, of pure cyan). The 8-bit RGB hexcone (256 values
    // each for red, green, blue) really only allows for 1530 distinct hues
    // (not 1536, more on that below), but the full unsigned 16-bit type was
    // chosen for hue so that one's code can easily handle a contiguous color
    // wheel by allowing hue to roll over in either direction.
    hue = (hue * 1530L + 32768) / 65536;
    // Because red is centered on the rollover point (the +32768 above,
    // essentially a fixed-point +0.5), the above actually yields 0 to 1530,
    // where 0 and 1530 would yield the same thing. Rather than apply a
    // costly modulo operator, 1530 is handled as a special case below.

    // So you'd think that the color "hexcone" (the thing that ramps from
    // pure red, to pure yellow, to pure green and so forth back to red,
    // yielding six slices), and with each color component having 256
    // possible values (0-255), might have 1536 possible items (6*256),
    // but in reality there's 1530. This is because the last element in
    // each 256-element slice is equal to the first element of the next
    // slice, and keeping those in there this would create small
    // discontinuities in the color wheel. So the last element of each
    // slice is dropped...we regard only elements 0-254, with item 255
    // being picked up as element 0 of the next slice. Like this:
    // Red to not-quite-pure-yellow is:        255,   0, 0 to 255, 254,   0
    // Pure yellow to not-quite-pure-green is: 255, 255, 0 to   1, 255,   0
    // Pure green to not-quite-pure-cyan is:     0, 255, 0 to   0, 255, 254
    // and so forth. Hence, 1530 distinct hues (0 to 1529), and hence why
    // the constants below are not the multiples of 256 you might expect.

    // Convert hue to R,G,B (nested ifs faster than divide+mod+switch):
    if (hue < 510) {         // Red to Green-1
        b = 0;
        if (hue < 255) {     //   Red to Yellow-1
            r = 255;
            g = hue;         //     g = 0 to 254
        } else {             //   Yellow to Green-1
            r = 510 - hue;   //     r = 255 to 1
            g = 255;
        }
    } else if (hue < 1020) { // Green to Blue-1
        r = 0;
        if (hue <  765) {    //   Green to Cyan-1
            g = 255;
            b = hue - 510;   //     b = 0 to 254
        } else {             //   Cyan to Blue-1
            g = 1020 - hue;  //     g = 255 to 1
            b = 255;
        }
    } else if (hue < 1530) { // Blue to Red-1
        g = 0;
        if (hue < 1275) {    //   Blue to Magenta-1
            r = hue - 1020;  //     r = 0 to 254
            b = 255;
        } else {             //   Magenta to Red-1
            r = 255;
            b = 1530 - hue;  //     b = 255 to 1
        }
    } else {                 // Last 0.5 Red (quicker than % operator)
        r = 255;
        g = b = 0;
    }

    // Apply saturation and value to R,G,B, pack into 32-bit result:
    uint32_t v1 =   1 + val; // 1 to 256; allows >>8 instead of /255
    uint16_t s1 =   1 + sat; // 1 to 256; same reason
    uint8_t  s2 = 255 - sat; // 255 to 0
    return ((((((r * s1) >> 8) + s2) * v1) & 0xff00) << 8) |
           (((((g * s1) >> 8) + s2) * v1) & 0xff00)       |
           (((((b * s1) >> 8) + s2) * v1)           >> 8);
}

/*!
   @brief   Query the color of a previously-set pixel.
   @param   n  Index of pixel to read (0 = first).
   @return  'Packed' 32-bit RGB or WRGB value. Most significant byte is white
           (for RGBW pixels) or 0 (for RGB pixels), next is red, then green,
           and least significant byte is blue.
   @note    If the strip brightness has been changed from the default value
           of 255, the color read from a pixel may not exactly match what
           was previously written with one of the setPixelColor() functions.
           This gets more pronounced at lower brightness levels.
 */
uint32_t NeoPixel::getPixelColor(uint16_t n) const {
    if (n >= numLEDs) return 0;  // Out of bounds, return no color.

    uint8_t* p;

    if (wOffset == rOffset) { // Is RGB-type device
        p = &pixels[n * 3];
        if (brightness) {
            // Stored color was decimated by setBrightness(). Returned value
            // attempts to scale back to an approximation of the original 24-bit
            // value used when setting the pixel color, but there will always be
            // some error -- those bits are simply gone. Issue is most
            // pronounced at low brightness levels.
            return (((uint32_t)(p[rOffset] << 8) / brightness) << 16) |
                   (((uint32_t)(p[gOffset] << 8) / brightness) <<  8) |
                   ((uint32_t)(p[bOffset] << 8) / brightness);
        } else {
            // No brightness adjustment has been made -- return 'raw' color
            return ((uint32_t)p[rOffset] << 16) |
                   ((uint32_t)p[gOffset] <<  8) |
                   (uint32_t)p[bOffset];
        }
    } else {              // Is RGBW-type device
        p = &pixels[n * 4];
        if (brightness) { // Return scaled color
            return (((uint32_t)(p[wOffset] << 8) / brightness) << 24) |
                   (((uint32_t)(p[rOffset] << 8) / brightness) << 16) |
                   (((uint32_t)(p[gOffset] << 8) / brightness) <<  8) |
                   ((uint32_t)(p[bOffset] << 8) / brightness);
        } else { // Return raw color
            return ((uint32_t)p[wOffset] << 24) |
                   ((uint32_t)p[rOffset] << 16) |
                   ((uint32_t)p[gOffset] <<  8) |
                   (uint32_t)p[bOffset];
        }
    }
}

/*!
   @brief   Adjust output brightness. Does not immediately affect what's
           currently displayed on the LEDs. The next call to show() will
           refresh the LEDs at this level.
   @param   b  Brightness setting, 0=minimum (off), 255=brightest.
   @note    This was intended for one-time use in one's setup() function,
           not as an animation effect in itself. Because of the way this
           library "pre-multiplies" LED colors in RAM, changing the
           brightness is often a "lossy" operation -- what you write to
           pixels isn't necessary the same as what you'll read back.
           Repeated brightness changes using this function exacerbate the
           problem. Smart programs therefore treat the strip as a
           write-only resource, maintaining their own state to render each
           frame of an animation, not relying on read-modify-write.
 */
void NeoPixel::setBrightness(uint8_t b) {
    // Stored brightness value is different than what's passed.
    // This simplifies the actual scaling math later, allowing a fast
    // 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t,
    // adding 1 here may (intentionally) roll over...so 0 = max brightness
    // (color values are interpreted literally; no scaling), 1 = min
    // brightness (off), 255 = just below max brightness.
    uint8_t newBrightness = b + 1;

    if (newBrightness != brightness) { // Compare against prior value
        // Brightness has changed -- re-scale existing data in RAM,
        // This process is potentially "lossy," especially when increasing
        // brightness. The tight timing in the WS2811/WS2812 code means there
        // aren't enough free cycles to perform this scaling on the fly as data
        // is issued. So we make a pass through the existing color data in RAM
        // and scale it (subsequent graphics commands also work at this
        // brightness level). If there's a significant step up in brightness,
        // the limited number of steps (quantization) in the old data will be
        // quite visible in the re-scaled version. For a non-destructive
        // change, you'll need to re-render the full strip data. C'est la vie.
        uint8_t c,
                * ptr         = pixels,
                oldBrightness = brightness - 1; // De-wrap old brightness value
        uint16_t scale;
        if (oldBrightness == 0) scale = 0;      // Avoid /0
        else if (b == 255) scale = 65535 / oldBrightness;
        else scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness;

        for (uint16_t i = 0; i<numBytes; i++) {
            c      = *ptr;
            *ptr++ = (c * scale) >> 8;
        }
        brightness = newBrightness;
    }
}

/*!
   @brief   Retrieve the last-set brightness value for the strip.
   @return  Brightness value: 0 = minimum (off), 255 = maximum.
 */
uint8_t NeoPixel::getBrightness(void) const {
    return brightness - 1;
}

/*!
   @brief   Fill the whole NeoPixel strip with 0 / black / off.
 */
void NeoPixel::clear(void) {
    memset(pixels, 0, numBytes);
}

// A 32-bit variant of gamma8() that applies the same function
// to all components of a packed RGB or WRGB value.
uint32_t NeoPixel::gamma32(uint32_t x) {
    uint8_t* y = (uint8_t*)&x;

    // All four bytes of a 32-bit value are filtered even if RGB (not WRGB),
    // to avoid a bunch of shifting and masking that would be necessary for
    // properly handling different endianisms (and each byte is a fairly
    // trivial operation, so it might not even be wasting cycles vs a check
    // and branch for the RGB case). In theory this might cause trouble *if*
    // someone's storing information in the unused most significant byte
    // of an RGB value, but this seems exceedingly rare and if it's
    // encountered in reality they can mask values going in or coming out.
    for (uint8_t i = 0; i<4; i++) y[i] = gamma8(y[i]);
    return x; // Packed 32-bit return
}